/**
 * MoveToFront.h
 * @author Baptiste Le Goff
 */

#ifndef __Compressor__MoveToFront__
#define __Compressor__MoveToFront__

#include <string>
#include <map>
#include <iostream>
#include <vector>

#include "../persistencia2/Archivo.h"
#include "../persistencia2/Bloque.h"

using namespace std;

class MoveToFront{

private:

	string subfijo_cod;

    public:

        /**
         * Contructor
         */
        MoveToFront();

        /**
         * Dictionary creation method
         * @return The dictionary containing all 256 ASCII chars
         */
        string makeDictionary();

        /**
         * Encoding method
         * @param input The text to encode
         * @return A vector containing the encoded text
         */
        std::vector<unsigned char> encode(std::vector<unsigned char> input);

        /**
         * Decoding method
         * @param moves Bloc of bytes to decode
         * @return A vector containing the decoded text
         */
        std::vector<unsigned char> decode(std::vector<unsigned char> moves);

        std::string codificar(std::string blocksorting_cod, unsigned int tam_bloque);

        std::string decodificar(std::string huffman_decod, unsigned int tam_bloque);

};


// %%%%%%%%%%%%%%%%%%% INLINE FUNCTIONS %%%%%%%%%%%%%%%%%%%


//Generic method for MTF and MTM
static inline string moveToPos(string s, int charPos, int newPos){
    char c = s[newPos];
    s[newPos] = s[charPos];
    int i = newPos + 1;

    while(i < charPos + 1){
        char tmp = s[i];
        s[i] = c;
        c = tmp;
        i++;
    }

    return s;
}

//Simple move to front
static inline string moveToFront(string s, int charPos){
    return moveToPos(s, charPos, 0);
}

//Move to middle
static inline string moveToMiddle(string s, int charPos){
    int middlePos = (s.length()/2);

    if(charPos < middlePos)
        cout << "Move To Middle : Unexpected Behavior" << endl;

    return moveToPos(s, charPos, middlePos);
}

//Initiliaze a new map with each key being in input and each value associated is 0
static inline std::map<char,int> initializeNewAppearanceMap(string input){
    map<char,int> res;
    for(int i=0; i<input.length(); i++){
        res[input[i]] = 0;
    }

    return res;
}

//Decides what to do between move to front and move to middle
static inline string makeTheMove(string dictionary, int charPos, std::map<char, int> &charAppeared){
    string res = dictionary;
    if(charAppeared[res[charPos]] == 1 && charPos > ((res.length() - 1)/2)){
        res = moveToMiddle(res, charPos);
    }

    else{
        charAppeared[res[charPos]] = 1;
        res = moveToFront(res, charPos);
    }
    return res;
}


#endif
